package com.ruoyi.app.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.crypto.digest.BCrypt;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.app.domain.*;
import com.ruoyi.app.domain.bo.*;
import com.ruoyi.app.domain.vo.*;
import com.ruoyi.app.mapper.AppFriendMapper;
import com.ruoyi.app.mapper.AppUserMapper;
import com.ruoyi.app.service.*;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BillType;
import com.ruoyi.common.enums.CoinType;
import com.ruoyi.common.enums.DetailEnums;
import com.ruoyi.common.enums.SexType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.redis.RedisUtils;
import com.ruoyi.im.core.TxTemplate;
import com.ruoyi.system.service.ISysConfigService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * APP用户信息Service业务层处理
 *
 * @author ruoyi
 * @date 2025-11-30
 */
@RequiredArgsConstructor
@Service
public class AppUserServiceImpl implements IAppUserService {


    private final AppUserMapper baseMapper;
    private final IAppAssetService appAssetService;
    private final IAppLevelService appLevelService;
    private final IAppSalesLevelService appSalesLevelService;
    private final ISysConfigService sysConfigService;
    private final IAppDetailService appDetailService;
    private final IAppUserVipService appUserVipService;
    private final IAppUserBagService iAppUserBagService;
    private final IAppUserImageService appUserImageService;
    private final IAppUserCodeService appUserCodeService;
    @Lazy
    private IAppPackageService appPackageService;
    @Lazy
    private IAppPackageOrderService appPackageOrderService;

    private TxTemplate txTemplate;



    /**
     * 查询APP用户信息
     */
    @Override
    public AppUserVo queryById(Long id) {
        AppUserVo userVo = baseMapper.selectVoById(id);
        if (Objects.isNull(userVo)) {
            return null;
        }
        userVo.setPassword(null);
        if (userVo.getBirthday() != null) {
            userVo.setAge(InfoUtils.getAge(userVo.getBirthday()));
        }
        userVo.setChatName(Constants.USER + userVo.getId());
        return userVo;
    }

    @Override
    public List<AppUserVo> queryByCode(String code) {
        LambdaQueryWrapper<AppUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AppUser::getCode, code);
        return baseMapper.selectVoList(wrapper);
    }

    @Override
    public List<AppUserVo> queryByPid(Long id) {
        LambdaQueryWrapper<AppUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AppUser::getParentId, id);
        return baseMapper.selectVoList(wrapper);
    }

    /**
     * 查询APP详细用户信息
     */
    @Override
    public UserVo queryByIdUserVo(Long id) {
        AppUserVo user = baseMapper.selectVoById(id);
        user.setPassword(null);
        user.setIsRealName(StringUtils.isNotBlank(user.getCode()));
        UserVo userVo = new UserVo();
        EntityCopyUtils.copyPropertiesIgnoreNull(user, userVo);
        if (userVo.getBirthday() != null) {
            userVo.setAge(InfoUtils.getAge(userVo.getBirthday()));
            userVo.setConstellation(InfoUtils.getConstellation(userVo.getBirthday()));
        }
        userVo.setVipVo(appUserVipService.userVipId(id));
        userVo.setLevelVo(appLevelService.queryById(userVo.getLevel()));
        userVo.setSalesLevelVo(appSalesLevelService.queryById(userVo.getSalesLevel()));
        return userVo;
    }

    /**
     * 过滤用户信息
     */
    @Override
    public UserResultVo filterateUserVo(AppUserVo user) {
        user.setIsRealName(StringUtils.isNotBlank(user.getCode()));
        user.setPassword(null);
        UserResultVo userVo = new UserResultVo();
        EntityCopyUtils.copyPropertiesIgnoreNull(user, userVo);
        if (userVo.getBirthday() != null) {
            userVo.setAge(InfoUtils.getAge(userVo.getBirthday()));
            userVo.setConstellation(InfoUtils.getConstellation(userVo.getBirthday()));
        }
        //VIP功能
        userVo.setVipVo(appUserVipService.userVipId(user.getId()));
        return userVo;
    }

    /**
     * 过滤用户信息
     */
    @Override
    public UserResultVo filterateUserVo(Long id) {
        AppUserVo user = baseMapper.selectVoById(id);
        user.setPassword(null);
        UserResultVo userVo = new UserResultVo();
        EntityCopyUtils.copyPropertiesIgnoreNull(user, userVo);
        if (userVo.getBirthday() != null) {
            userVo.setAge(InfoUtils.getAge(userVo.getBirthday()));
            userVo.setConstellation(InfoUtils.getConstellation(userVo.getBirthday()));
        }
        //会员功能
        userVo.setVipVo(appUserVipService.userVipId(id));
        return userVo;
    }


    /**
     * 查询APP详细用户信息
     */
    @Override
    public UserVo userVo(Long id) {
        AppUserVo user = baseMapper.selectVoById(id);
        UserVo userVo = new UserVo();
        EntityCopyUtils.copyPropertiesIgnoreNull(user, userVo);
        if (userVo.getBirthday() != null) {
            userVo.setAge(InfoUtils.getAge(userVo.getBirthday()));
            userVo.setConstellation(InfoUtils.getConstellation(userVo.getBirthday()));
        }
        userVo.setPhotos(appUserImageService.queryList(user.getId()));
        //VIP功能
        userVo.setVipVo(appUserVipService.userVipId(id));
        return userVo;
    }


    @Override
    public AppUserVo queryByPhone(String phone) {
        LambdaQueryWrapper<AppUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AppUser::getPhone, phone);
        return baseMapper.selectVoOne(wrapper);
    }

    @Override
    public AppUserVo queryByUniqueCode(String uniqueCode) {
        LambdaQueryWrapper<AppUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AppUser::getUniqueCode, uniqueCode);
        return baseMapper.selectVoOne(wrapper);
    }

    @Override
    public AppUserVo queryNickName(String name) {
        LambdaQueryWrapper<AppUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AppUser::getNickName, name);
        return baseMapper.selectVoOne(wrapper);
    }

    @Override
    public AppUserVo queryByInviteCode(String code) {
        LambdaQueryWrapper<AppUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AppUser::getInviteCode, code);
        return baseMapper.selectVoOne(wrapper);
    }

    @Override
    public List<AppUserVo> selectList(AppUserBo bo) {
        LambdaQueryWrapper<AppUser> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }


    @Override
    public List<AppUserVo> selectList(LambdaQueryWrapper<AppUser> lqw) {
        return baseMapper.selectVoList(lqw);
    }

    /**
     * 查询APP用户信息列表
     */
    @Override
    public TableDataInfo<AppUserVo> queryPageList(AppUserBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<AppUser> lqw = buildQueryWrapper(bo);
        Page<AppUserVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        if (!CollUtil.isEmpty(result.getRecords())){
            if (StringUtils.isNotBlank(bo.getPhone()) && bo.getTime()!=null){
                if (bo.getTime().length>0){
                    AppUserVo appUserVo = result.getRecords().get(0);
                    List<AppUserVo> appUserVos = zhituiList(appUserVo.getId());
                    List<AppUserVo> appUserVos1 = jiantuiList(appUserVo.getId());
                    CollUtil.addAll(result.getRecords(),appUserVos);
                    CollUtil.addAll(result.getRecords(),appUserVos1);
                }
            }
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询APP用户信息列表
     */
    @Override
    public TableDataInfo<AppUser> queryPage(AppUserBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<AppUser> lqw = buildQueryWrapper(bo);
        Page<AppUser> result = baseMapper.selectPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }


    /**
     * 查询APP用户信息列表
     */
    @Override
    public List<AppUserVo> queryList(AppUserBo bo) {
        LambdaQueryWrapper<AppUser> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    /**
     * 查询APP用户信息列表
     */
    @Override
    public List<AppUserVo> queryList(LambdaQueryWrapper<AppUser> wrapper) {
        return baseMapper.selectVoList(wrapper);
    }

    /**
     * 查询APP用户信息列表
     */
    @Override
    public List<AppUser> queryListUser(AppUserBo appUserBo) {
        LambdaQueryWrapper<AppUser> lqw = buildQueryWrapper(appUserBo);
        return baseMapper.selectList(lqw);
    }


    /**
     * 计算用户有几个共同爱好的标签
     *
     * @param labelIDs
     * @param labelLikeVos
     * @return
     */
    public long number(Set<Long> labelIDs, List<AppLabelLikeVo> labelLikeVos) {
        return labelLikeVos.stream().filter(i -> labelIDs.contains(i.getLabelId())).count();
    }

    /**
     * 获取用户的信息
     *
     * @param ids 用户ID
     * @return
     */
    public List<AppUserVo> info(HashSet<Long> ids) {
        ArrayList<AppUserVo> userVos = new ArrayList<>();
        ids.forEach(e -> {
            AppUserVo userVo = queryById(e);
            userVo.setChatName(Constants.USER + e);
            userVos.add(userVo);
        });
        return userVos;
    }


    @Override
    public List<AppUserVo> queryListOrder(AppUserBo bo) {
        LambdaQueryWrapper<AppUser> lqw = buildQueryWrapper(bo);
        lqw.orderByDesc(AppUser::getId);
        return baseMapper.selectVoList(lqw);
    }

    @Override
    public List<AppUserVo> queryList(AppUserSettingVo setting, Set<Long> noLikeIds) {
        noLikeIds.add(setting.getUserId());
        LambdaQueryWrapper<AppUser> lqw = Wrappers.lambdaQuery();
        lqw.notIn(AppUser::getId, noLikeIds);
        if (!SexType.UN.getCode().equals(setting.getSex())) {
            lqw.eq(AppUser::getSex, setting.getSex());
        }
        if (setting.getDistance() != null && setting.getDistance() > 0 && setting.getDistance() < 100) {
            if (setting.getLatitude() != null && setting.getLongitude() != null) {
                Map<String, Double> doubleMap = DistanceUtils.getPeopleNearby(setting.getLongitude(), setting.getLatitude(), setting.getDistance());
                lqw.le(AppUser::getLatitude, doubleMap.get("maxLatitude"));
                lqw.ge(AppUser::getLatitude, doubleMap.get("minLatitude"));
                lqw.le(AppUser::getLongitude, doubleMap.get("maxLongitude"));
                lqw.ge(AppUser::getLongitude, doubleMap.get("minLongitude"));
            }
        }
        //年龄越小，时间戳越大
        if (setting.getAgeMin().equals(setting.getAgeMax())) {
            String minString = newDateUtil.subYearNew(new Date(), setting.getAgeMin()) + "-01-01 00:00:00";
            long minLong = newDateUtil.toMillSeconds(minString);
            String maxString = newDateUtil.subYearNew(new Date(), setting.getAgeMax()) + "-12-31 23:59:59";
            long maxLong = newDateUtil.toMillSeconds(maxString);
            lqw.ge(AppUser::getBirthday, minLong).le(AppUser::getBirthday, maxLong);
        } else {
            String minString = newDateUtil.subYearNew(new Date(), setting.getAgeMin()) + "-12-31 23:59:59";
            long minLong = newDateUtil.toMillSeconds(minString);
            String maxString = newDateUtil.subYearNew(new Date(), setting.getAgeMax()) + "-01-01 00:00:00";
            long maxLong = newDateUtil.toMillSeconds(maxString);
            lqw.le(AppUser::getBirthday, minLong).ge(AppUser::getBirthday, maxLong);
        }
        return baseMapper.selectVoList(lqw);
    }

    @Override
    public List<AppUserVo> findList(AppUserBo bo) {
        LambdaQueryWrapper<AppUser> lqw = wrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    @Override
    public List<AppUserVo> findNameList(AppUserBo bo) {
        LambdaQueryWrapper<AppUser> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getUserName()), AppUser::getUserName, bo.getUserName()).or().like(StringUtils.isNotBlank(bo.getNickName()), AppUser::getNickName, bo.getNickName());
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<AppUser> buildQueryWrapper(AppUserBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<AppUser> lqw = Wrappers.lambdaQuery();
        lqw.like(bo.getId() != null, AppUser::getId, bo.getId());
        lqw.like(StringUtils.isNotBlank(bo.getUserName()), AppUser::getUserName, bo.getUserName());
        lqw.like(StringUtils.isNotBlank(bo.getNickName()), AppUser::getNickName, bo.getNickName());
        lqw.eq(StringUtils.isNotBlank(bo.getEmail()), AppUser::getEmail, bo.getEmail());
        lqw.like(StringUtils.isNotBlank(bo.getPhone()), AppUser::getPhone, bo.getPhone());
        lqw.eq(StringUtils.isNotBlank(bo.getSex()), AppUser::getSex, bo.getSex());
        lqw.eq(StringUtils.isNotBlank(bo.getInviteCode()), AppUser::getInviteCode, bo.getInviteCode());
        lqw.eq(bo.getParentId() != null, AppUser::getParentId, bo.getParentId());
        lqw.eq(StringUtils.isNotBlank(bo.getAvatar()), AppUser::getAvatar, bo.getAvatar());
        lqw.eq(StringUtils.isNotBlank(bo.getPassword()), AppUser::getPassword, bo.getPassword());
        lqw.eq(StringUtils.isNotBlank(bo.getOccupation()), AppUser::getOccupation, bo.getOccupation());
        lqw.eq(StringUtils.isNotBlank(bo.getSchool()), AppUser::getSchool, bo.getSchool());
        lqw.eq(bo.getBirthday() != null, AppUser::getBirthday, bo.getBirthday());
        lqw.eq(bo.getHeight() != null, AppUser::getHeight, bo.getHeight());
        lqw.eq(StringUtils.isNotBlank(bo.getRegister()), AppUser::getRegister, bo.getRegister());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), AppUser::getStatus, bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getLoginIp()), AppUser::getLoginIp, bo.getLoginIp());
        lqw.eq(bo.getLoginDate() != null, AppUser::getLoginDate, bo.getLoginDate());
        lqw.in(bo.getUserIds() != null && !bo.getUserIds().isEmpty(), AppUser::getParentId, bo.getUserIds());
        lqw.eq(bo.getLevel() != null, AppUser::getLevel, bo.getLevel());
        lqw.eq(bo.getSalesLevel() != null, AppUser::getSalesLevel, bo.getSalesLevel());
        lqw.eq(StringUtils.isNotBlank(bo.getUniqueCode()), AppUser::getUniqueCode, bo.getUniqueCode());
        if (StringUtils.isNotBlank(bo.getRealStatus())) {
            if (StringUtils.equals(bo.getRealStatus(), Constants.FAIL)) {
                lqw.isNotNull(AppUser::getCode);
            } else {
                lqw.isNull(AppUser::getCode);
            }
        }
        return lqw;
    }

    private LambdaQueryWrapper<AppUser> wrapper(AppUserBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<AppUser> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getNickName()), AppUser::getNickName, bo.getNickName()).or().eq(StringUtils.isNotBlank(bo.getPhone()), AppUser::getPhone, bo.getPhone());
        return lqw;
    }

    /**
     * 新增APP用户信息
     */
    @Override
    public Boolean insertByBo(AppUserBo bo) {
        AppUser add = BeanUtil.toBean(bo, AppUser.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 新增APP用户信息
     */
    @Override
    public Boolean insert(AppUserVo userVo) {
        AppUser user = BeanUtil.toBean(userVo, AppUser.class);
        user.setCreateBy(userVo.getUserName());
        user.setCreateTime(DateUtils.getNowDate());
        user.setUpdateBy(userVo.getUserName());
        user.setUpdateTime(DateUtils.getNowDate());
        boolean flag = baseMapper.insert(user) > 0;
        if (flag) {
            userVo.setId(user.getId());
        }
        return flag;
    }

    /**
     * 修改APP用户信息
     */
    @Override
    public Boolean updateByBo(AppUserBo bo) {
        AppUser update = BeanUtil.toBean(bo, AppUser.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 修改APP用户信息
     */
    @Override
    public Boolean updateByVo(AppUserVo bo) {
        AppUser update = BeanUtil.toBean(bo, AppUser.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 修改APP用户信息
     */
    @Override
    public Boolean update(LambdaUpdateWrapper<AppUser> wrapper) {
        return baseMapper.update(null, wrapper) > 0;
    }

    @Override
    public Boolean updates(List<AppUserVo> appUserVos) {
        return null;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(AppUser entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除APP用户信息
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public HashMap<String, Object> inviteCode(Long uid) {
        AppUserVo user = queryById(uid);
        if (StringUtils.isBlank(user.getInviteCode())) {
            user.setInviteCode(ShareCodeUtil.getSerialCode(user.getId().intValue()));
            AppUserBo userBo = BeanUtil.toBean(user, AppUserBo.class);
            updateByBo(userBo);
        }
        List<AppLevelVo> appLevelRateVos = appLevelService.queryList(new AppLevelBo());
        Map<Long, AppLevelVo> level = appLevelRateVos.stream().collect(Collectors.toMap(AppLevelVo::getId, e -> e));
        HashMap<String, Object> hashMap = new HashMap<>();
        /**
         * 总活跃度 : 直推一个人，一个活跃度，10个任务包一个活跃度
         * 自己下级所有人 无限层 每个人本身 1 活跃度 + 每个人的任务包（10=1） 比如100任务包是10活跃度
         *
         *  联盟活跃度: 直推一个活跃度，间推一个活跃度，活跃度加起来
         * 每个人本身 1 活跃度 + 每个人的任务包（10=1） 比如100任务包是10活跃度
         *

         *
         *
         * 团队总人数 是他直推的所有人有没有实名的都算一个团队人数
         * 团队活跃度 是这37个人， 所有下级 有几个人做任务就显示在这上面
         * 团队活跃人数 就是他直推下面所有人的。每天看6广告就算一个人。
         */
        long l = System.currentTimeMillis();
        hashMap.put("inviteCode", user.getInviteCode());
        String inviteUrl = Constants.INVITE_URL + user.getInviteCode();
        hashMap.put("inviteUrl", inviteUrl);
        String inviteCodeImage = null;
        try {
            String base64 = CreateImageUtils.generateQRCodeBase64(inviteUrl, 250, 250);
            inviteCodeImage = "data:image/png;base64," + base64;
        } catch (Exception k) {
            inviteCodeImage = "";
        }
        hashMap.put("inviteCodeImage", inviteCodeImage);
        hashMap.put("isBind", user.getParentId() != null);
        if (user.getParentId() != null) {
            AppUserVo userVo = queryById(user.getParentId());
            String phone = userVo.getPhone().substring(0, 3) + "****" + userVo.getPhone().substring(7);
            hashMap.put("parentPhone", phone);
            hashMap.put("parentId", user.getParentId());
        }
        hashMap.put("levelId", level.get(user.getLevel()).getId());
        hashMap.put("levelName", level.get(user.getLevel()).getName());
        List<AppUserVo> userVos = zhituiList(uid);
        //团队总人数
        hashMap.put("teamUserNumber", (userVos.size()));
        List<Long> ids = userVos.stream().map(AppUserVo::getId).collect(Collectors.toList());
        if (!ids.isEmpty()) {
            LambdaQueryWrapper<AppAsset> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(AppAsset::getUserId, ids);
            List<AppAssetVo> assetVos = appAssetService.queryList(wrapper);
            List<AppAssetVo> collect = assetVos.stream().filter(e -> e.getLiveness().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
            //团队活跃人数  显示的是没做任务的
            hashMap.put("teamActiveUserNumber", teamActiveUserNumber(userVos));
            BigDecimal reduce = collect.stream().map(AppAssetVo::getLiveness).reduce(BigDecimal.ZERO, BigDecimal::add);
            //团队活跃度
            hashMap.put("teamActiveNumber", teamActive(userVos));
        } else {
            //团队活跃人数
            hashMap.put("teamActiveUserNumber", 0);
            //团队活跃度
            hashMap.put("teamActiveNumber", 0);
        }
        //总活跃度

        Integer total = getTotalLive(uid) + userVos.size();
        hashMap.put("sumActiveNumber", total);
        //联盟活跃度
        if (!ids.isEmpty()) {
            hashMap.put("unionActiveNumber", lianMeng(userVos,jiantuiList(uid)));
        } else {
            hashMap.put("unionActiveNumber", 0);
        }
        long l1 = System.currentTimeMillis();
        hashMap.put("time", l1 - l);
        //耗时秒数


        return hashMap;
        /**
         * 总活跃度: 自己下面所有人 无限层 每个人的本身 1 活跃度 + 每个人的十个任务包 1活跃度 + 每个人的直推间推活跃度
         * 联盟活跃度: 自己下面所有人 无限层 每个人的十个任务包 1活跃度
         */
    }

    private Object teamActive(List<AppUserVo> userVos) {
        //团队活跃度
        String typeKey = CacheConstants.ADVERTISING;
        //是这37个人， 所有下级 有几个人做任务就显示在这上面
        int total = 0;
        for (AppUserVo child : userVos) {
            String key = typeKey + child.getId();
            if (RedisUtils.hasKey(key)){
                if ((int)RedisUtils.getCacheObject(key)==6){
                    total++;
                }
            }
            total += getTotalLive(child.getId()); // 递归往下查
        }
        return total;
    }


    private Object lianMeng(List<AppUserVo> zhiTui,List<AppUserVo> jianTui) {
        //联盟活跃度: 直推一个活跃度，间推一个活跃度，活跃度加起来
        //         * 每个人本身 1 活跃度 + 每个人的任务包（10=1） 比如100任务包是10活跃度

        //自己的也算
        int sum  = 0;

        if (zhiTui.isEmpty() && jianTui.isEmpty()){
            return sum;
        }

        zhiTui = zhiTui.stream().filter(e -> e.getCode() != null).collect(Collectors.toList());

        jianTui = jianTui.stream().filter(e -> e.getCode() != null).collect(Collectors.toList());


        //这个1 是自己
        sum = sum + zhiTui.size() + jianTui.size() + 1;


        Collection<AppUserVo> union = CollUtil.union(zhiTui, jianTui);

        List<Long> collect = union.stream().map(AppUserVo::getId).collect(Collectors.toList());


        Long userId = LoginHelper.getUserId();
        collect.add(userId);

        if (collect.isEmpty()){
            return 0;
        }

        //查询他们的包
        AppPackageOrderServiceImpl appPackageOrderService = SpringUtil.getBean(AppPackageOrderServiceImpl.class);
        List<AppPackageOrder> appPackageOrders = appPackageOrderService.getPageOrder(collect);


        BigDecimal sumData = BigDecimal.valueOf(sum);

        if (!appPackageOrders.isEmpty()){
            for (AppPackageOrder appPackageOrder : appPackageOrders) {
                if (appPackageOrder.getPackagePrice().compareTo(BigDecimal.ZERO) > 0){
                    BigDecimal divide = appPackageOrder.getPackagePrice().divide(BigDecimal.valueOf(10));
                    sumData.add(divide);
                }
            }




        }



        return sumData;
    }


    private Object lianMeng(List<AppUserVo> zhiTui,List<AppUserVo> jianTui,Long userId) {
        //联盟活跃度: 直推一个活跃度，间推一个活跃度，活跃度加起来
        //         * 每个人本身 1 活跃度 + 每个人的任务包（10=1） 比如100任务包是10活跃度

        //自己的也算
        int sum  = 0;

        if (zhiTui.isEmpty() && jianTui.isEmpty()){
            return sum;
        }

        zhiTui = zhiTui.stream().filter(e -> e.getCode() != null).collect(Collectors.toList());

        jianTui = jianTui.stream().filter(e -> e.getCode() != null).collect(Collectors.toList());


        //这个1 是自己
        sum = sum + zhiTui.size() + jianTui.size() + 1;


        Collection<AppUserVo> union = CollUtil.union(zhiTui, jianTui);

        List<Long> collect = union.stream().map(AppUserVo::getId).collect(Collectors.toList());


        collect.add(userId);

        if (collect.isEmpty()){
            return 0;
        }

        //查询他们的包
        AppPackageOrderServiceImpl appPackageOrderService = SpringUtil.getBean(AppPackageOrderServiceImpl.class);
        List<AppPackageOrder> appPackageOrders = appPackageOrderService.getPageOrder(collect);


        BigDecimal sumData = BigDecimal.valueOf(sum);

        if (!appPackageOrders.isEmpty()){
            for (AppPackageOrder appPackageOrder : appPackageOrders) {
                if (appPackageOrder.getPackagePrice().compareTo(BigDecimal.ZERO) > 0){
                    BigDecimal divide = appPackageOrder.getPackagePrice().divide(BigDecimal.valueOf(10));
                    sumData.add(divide);
                }
            }




        }



        return sumData.intValue();
    }

    private Object teamActiveUserNumber(List<AppUserVo> userVos) {
        //团队活跃人数
        if (userVos.isEmpty()){
            return 0;
        }
        userVos = userVos.stream().filter(e -> e.getCode() != null).collect(Collectors.toList());

        int total = 0;
        String typeKey = CacheConstants.ADVERTISING;
        for (AppUserVo child : userVos) {
            String key = typeKey + child.getId();
            if (RedisUtils.hasKey(key)){
                if ((int)RedisUtils.getCacheObject(key)==6){
                    total++;
                }
            }
        }

        return  total ;
    }

    private int getTotalLive2(Long uid) {
        LambdaQueryWrapper<AppUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.isNotNull(AppUser::getCode);
        wrapper.eq(AppUser::getParentId, uid);

        List<AppUserVo> children = queryList(wrapper);
        int total = 0; // 先加上这一层
        for (AppUserVo child : children) {
            String key = "liveIf:"+ child.getId();
            if (RedisUtils.hasKey(key)){
                total++;
            }
            total += getTotalLive2(child.getId()); // 递归往下查
        }
        return total;
    }

    //查找这个人下的总活跃度 无限层
    private Integer getTotalLive(Long uid) {
        LambdaQueryWrapper<AppUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.isNotNull(AppUser::getCode);
        wrapper.eq(AppUser::getParentId, uid);

        List<AppUserVo> children = queryList(wrapper);
        int total = 0; // 先加上这一层
        String typeKey = CacheConstants.ADVERTISING;
        for (AppUserVo child : children) {
            String key = typeKey + child.getId();
            if (RedisUtils.hasKey(key)){
                if ((int)RedisUtils.getCacheObject(key)==6){
                    total++;
                }
            }
            total += getTotalLive(child.getId()); // 递归往下查
        }
        return total;
    }

    public static List<AppAssetVo> removeMinMaxLiveness(List<AppAssetVo> appAssetVos) {
        if (appAssetVos == null || appAssetVos.size() <= 2) {
            return appAssetVos; // 无需处理
        }
        // 按liveness升序排序
        List<AppAssetVo> sortedList = appAssetVos.stream()
            .sorted(Comparator.comparing(AppAssetVo::getLiveness))
            .collect(Collectors.toList());
        // 移除首尾各一条数据（最小和最大值）
        return sortedList.subList(1, sortedList.size() - 1);
    }

    @Override
    public Boolean updatePassword(Long userId, String password) {
        return baseMapper.update(null, new LambdaUpdateWrapper<AppUser>().set(AppUser::getPassword, BCrypt.hashpw(password)).eq(AppUser::getId, userId)) > 0;
    }

    @Override
    public Boolean updateParent(Long userId, Long parentId) {
        return baseMapper.update(null, new LambdaUpdateWrapper<AppUser>().set(AppUser::getParentId, parentId).eq(AppUser::getId, userId)) > 0;
    }

    @Override
    public Boolean updateParentAndAward(Long userId, Long parentId) {
        updateParent(userId, parentId);
        AppUserBagVo appUserBagVo = iAppUserBagService.queryByUserId(userId, Constants.FAIL);
        if (Objects.nonNull(appUserBagVo)) {
            appUserBagVo.setNumber(appUserBagVo.getNumber() + 1);
            return iAppUserBagService.updateByVo(appUserBagVo);
        } else {
            AppUserBagBo appUserBag = new AppUserBagBo();
            appUserBag.setNumber(1);
            appUserBag.setUserId(userId);
            appUserBag.setType("1");
            return iAppUserBagService.insertByBo(appUserBag);
        }
    }


    @Override
    public Boolean updateUuid(Long userId, String uuid) {
        return baseMapper.update(null, new LambdaUpdateWrapper<AppUser>().set(AppUser::getUuid, uuid).eq(AppUser::getId, userId)) > 0;
    }

    @Override
    public Boolean updateStatus(Long userId, String status) {
        AppUserVo userVo = queryById(userId);
        return baseMapper.update(null, new LambdaUpdateWrapper<AppUser>().set(AppUser::getStatus, status).set(AppUser::getUserName, userVo.getUserName() + "_off").set(AppUser::getPhone, userVo.getPhone() + "_off").eq(AppUser::getId, userId)) > 0;
    }


    @Override
    public Boolean updateInfo(AppUserBo bo) {
        return updateByBo(bo);
    }

    /**
     * 查询用户信息
     *
     * @param id     查询用户信息的ID
     * @param userId 当前用户ID
     * @return
     */
    @Override
    public UserVo setUserInfo(Long id, Long userId) {
        UserVo user = queryByIdUserVo(id);
        user.setUuid(null);
        return user;
    }

    @Override
    public Boolean updateOnline(Long id) {
        LambdaUpdateWrapper<AppUser> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(AppUser::getId, id).set(AppUser::getOnlineStatus, Constants.SUCCESS);
        return baseMapper.update(null, wrapper) > 0;
    }

    @Override
    public Boolean update(ArrayList<AppUser> updates) {
        return baseMapper.updateBatchById(updates);
    }

    @Override
    public List<AppUserVo> zhituiList(Long id) {
        AppUserBo appUserBo = new AppUserBo();
        appUserBo.setParentId(id);
        return queryList(appUserBo);
    }

    @Override
    public List<AppUserVo> jiantuiList(Long id) {
        List<AppUserVo> users = zhituiList(id);
        if (users.isEmpty()) {
            return new ArrayList<>();
        }
        List<Long> ids = users.stream().map(AppUserVo::getId).collect(Collectors.toList());
        LambdaQueryWrapper<AppUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(AppUser::getParentId, ids);
        return baseMapper.selectVoList(wrapper);
    }

    @Override
    public List<AppUserVo> allList(Long id) {
        List<AppUserVo> users = zhituiList(id);
        if (users.isEmpty()) {
            return new ArrayList<>();
        }
        List<Long> ids = users.stream().map(AppUserVo::getId).collect(Collectors.toList());
        LambdaQueryWrapper<AppUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(AppUser::getParentId, ids);
        List<AppUserVo> erList = baseMapper.selectVoList(wrapper);
        if (!erList.isEmpty()) {
            users.addAll(erList);
        }
        return users;
    }

    public List<Long> findAllParentIds(Long userId) {
        List<Long> result = new ArrayList<>();
        // 查询当前用户信息
        AppUserVo currentUser = queryById(userId);
        if (currentUser == null || currentUser.getParentId() == null) {
            return result;
        }
        // 递归查询父级
        recursiveFindParent(currentUser.getParentId(), result);
        return result;
    }


    private void recursiveFindParent(Long parentId, List<Long> result) {
        if (parentId == null) return;
        // 添加当前父级ID到结果集
        result.add(parentId);
        // 查询父级用户的父ID
        AppUserVo parentUser = queryById(parentId);
        if (parentUser != null && parentUser.getParentId() != null) {
            recursiveFindParent(parentUser.getParentId(), result);
        }
    }


    /**
     * 更新用户等级
     *
     * @param userId 用户ID
     */
    @Override
    public Boolean updateUseLevel(Long userId) {
        //父级别
        System.out.println("用户注册升级上级开始执行：" + userId);
        AppUserVo appUserVo = queryById(userId);
        Long level = appUserVo.getLevel();
        if (level >= 7) {    //已经达到最高级
            return false;
        }
        int sign = 0;
        long next = level + 1;
        List<AppUserVo> ztList = zhituiList(userId);
        List<AppUserVo> jtList = jiantuiList(userId);
        List<AppLevelVo> appLevelRateVos = appLevelService.queryList(new AppLevelBo());
        Map<Long, AppLevelVo> levelList = appLevelRateVos.stream().collect(Collectors.toMap(AppLevelVo::getId, e -> e));
        AppLevelVo nextLevel = levelList.get(next);
        //现在上星看两个，一个是团队活跃度，一个是联盟活跃度
        int lianMeng = (int) lianMeng(ztList, jtList,userId);
        int teamActive = (int) teamActive(ztList);
        if (lianMeng>=nextLevel.getActiveMax() && teamActive >= nextLevel.getActiveMin()) {
            sign = 1;
        }
        if (sign == 1) {
            appUserVo.setLevel(next);
            if (updateByVo(appUserVo)) {
                if (nextLevel.getIntegralNumber() > 0) {
                    BigDecimal amount = new BigDecimal(nextLevel.getIntegralNumber());

                    //升级之后送对应任务包 查询对应价格的任务包
                    AppPackage appPackage = appPackageService.selByPrice(amount);

                    if (appPackage != null){

                        //送出任务包 当天给收益 并且记录是否给过包 如果给过则不再个给
                        String pageKey = "packAge"+":" + nextLevel + "-" + appUserVo.getId();
                        if (!RedisUtils.hasKey(pageKey)){
                            appPackageOrderService.sendPackage(appPackage, appUserVo.getId());
                            RedisUtils.setCacheObject(pageKey, "1");
                        }



                    }

                }
            }
        }
        //3.每个新用户推广一个人完成 7天看6个广告 释放10个贡献值 且实名
        //直推1人增加10贡献值
        String key = "7dayContribution:" + appUserVo.getId();
        if (RedisUtils.hasKey(key)){
            if (appUserVo.getCode()!=null){
                if (RedisUtils.getCacheObject(key).equals("7")){
                    appAssetService.addContribution(appUserVo.getId(), new BigDecimal(10));
                    appDetailService.insert(appUserVo.getId(), new BigDecimal(10), BigDecimal.ZERO,
                            BillType.IN.getCode(), CoinType.CONTRIBUTION.getCode(), DetailEnums.REGISTER_REWARD.getCode(),
                            "推广下级奖励", null);
                }
            }
        }
        //推广下级 直推奖励 0.6积分 间推0.3积分
//        if (appUserVo.getCode()!=null){
//            System.out.println("用户注册升级上级结束执行：" + userId);
//            appAssetService.addIntegral(appUserVo.getId(), new BigDecimal("0.6"));
//            appDetailService.insert(appUserVo.getId(), new BigDecimal("0.6"), BigDecimal.ZERO,
//                    BillType.IN.getCode(), CoinType.INTE.getCode(), DetailEnums.REGISTER_REWARD.getCode(),
//                    "直推奖励", null);
//            if (appUserVo.getParentId() != null){
//                appAssetService.addIntegral(appUserVo.getParentId(), new BigDecimal("0.3"));
//                appDetailService.insert(appUserVo.getParentId(), new BigDecimal("0.3"), BigDecimal.ZERO,
//                        BillType.IN.getCode(), CoinType.INTE.getCode(), DetailEnums.REGISTER_REWARD.getCode(),
//                        "间推奖励", null);
//            }
//        }
        return true;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void recommendedRewards(Long id, String ztRewards, String jtRewards) {
        AppUserVo appUserVo = queryById(id);
        if (appUserVo != null && appUserVo.getParentId() != null) {
            BigDecimal ztBigDecimal = new BigDecimal(ztRewards);
            if (ztBigDecimal.compareTo(BigDecimal.ZERO) > 0) {
                appAssetService.addIntegral(appUserVo.getParentId(), ztBigDecimal);
                appDetailService.insert(appUserVo.getParentId(), ztBigDecimal,
                        BigDecimal.ZERO, BillType.IN.getCode(), CoinType.INTE.getCode(),
                        DetailEnums.REGISTER_REWARD.getCode(), "注册实名直推奖励", id);
            }
            AppUserVo userVo = queryById(appUserVo.getParentId());
            if (userVo != null && userVo.getParentId() != null) {
                BigDecimal jtBigDecimal = new BigDecimal(jtRewards);
                if (jtBigDecimal.compareTo(BigDecimal.ZERO) > 0) {
                    appAssetService.addIntegral(userVo.getParentId(), jtBigDecimal);
                    appDetailService.insert(userVo.getParentId(), jtBigDecimal, BigDecimal.ZERO, BillType.IN.getCode(), CoinType.INTE.getCode(), DetailEnums.REGISTER_REWARD.getCode(), "注册实名间推奖励", id);
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void adRewards(Long id, BigDecimal integral) {
//        AppUserVo appUserVo = queryById(id);
//        if (appUserVo != null && appUserVo.getParentId() != null) {
//            String zhiTui = sysConfigService.selectConfigByKey("app.ad.zhitui");
//            BigDecimal ztBigDecimal = integral.multiply(new BigDecimal(zhiTui)).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
//            if (ztBigDecimal.compareTo(BigDecimal.ZERO) > 0) {
//                appAssetService.addIntegral(appUserVo.getParentId(), ztBigDecimal);
//                appDetailService.insert(appUserVo.getParentId(), ztBigDecimal, BigDecimal.ZERO, BillType.IN.getCode(), CoinType.INTE.getCode(), DetailEnums.SEE_ADS_REWARD.getCode(), "看广告直推奖励", id);
//            }
//            AppUserVo userVo = queryById(appUserVo.getParentId());
//            if (userVo != null && userVo.getParentId() != null) {
//                String jianTui = sysConfigService.selectConfigByKey("app.ad.jiantui");
//                BigDecimal jtBigDecimal = integral.multiply(new BigDecimal(jianTui)).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
//                if (jtBigDecimal.compareTo(BigDecimal.ZERO) > 0) {
//                    appAssetService.addIntegral(userVo.getParentId(), jtBigDecimal);
//                    appDetailService.insert(userVo.getParentId(), jtBigDecimal, BigDecimal.ZERO, BillType.IN.getCode(), CoinType.INTE.getCode(), DetailEnums.SEE_ADS_REWARD.getCode(), "看广告间推奖励", id);
//                }
//            }
//        }
    }

    /**
     * 爬塔推荐奖励
     *
     * @param id       用户ID
     * @param integral 奖励
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void paTaRewards(Long id, BigDecimal integral,String name) {
        AppUserVo appUserVo = queryById(id);
        if (appUserVo != null && appUserVo.getParentId() != null) {
            String zhiTui = sysConfigService.selectConfigByKey("app.pa.zhitui");
            //直推给上家15%
            BigDecimal ztBigDecimal = integral.multiply(new BigDecimal(zhiTui)).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
            if (ztBigDecimal.compareTo(BigDecimal.ZERO) > 0) {
                appAssetService.addIntegral(appUserVo.getParentId(), ztBigDecimal);
                appDetailService.insert(appUserVo.getParentId(), ztBigDecimal,
                        BigDecimal.ZERO, BillType.IN.getCode(), CoinType.INTE.getCode(),
                        DetailEnums.CLIMBING_TOWER_PA.getCode(), "爬塔"+name+"直推奖励", id);
            }
            AppUserVo userVo = queryById(appUserVo.getParentId());
            //间推给上家10%
            if (userVo != null && userVo.getParentId() != null) {
                String jianTui = sysConfigService.selectConfigByKey("app.pa.jiantui");
                BigDecimal jtBigDecimal = integral.multiply(new BigDecimal(jianTui)).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
                if (jtBigDecimal.compareTo(BigDecimal.ZERO) > 0) {
                    appAssetService.addIntegral(userVo.getParentId(), jtBigDecimal);
                    appDetailService.insert(userVo.getParentId(), jtBigDecimal,
                            BigDecimal.ZERO, BillType.IN.getCode(), CoinType.INTE.getCode(),
                            DetailEnums.CLIMBING_TOWER_PA.getCode(), "爬塔"+name+"间推奖励", id);
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void pageOrderRewards(Long id, BigDecimal income, String packageName) {
        //任务包推荐奖励
        AppUserVo appUserVo = queryById(id);
        if (appUserVo != null && appUserVo.getParentId() != null) {
            String zhiTui = "30";
            //直推给上家30%
            BigDecimal ztBigDecimal = income.multiply(new BigDecimal(zhiTui)).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
            if (ztBigDecimal.compareTo(BigDecimal.ZERO) > 0) {
                appAssetService.addIntegral(appUserVo.getParentId(), ztBigDecimal);
                appDetailService.insert(appUserVo.getParentId(), ztBigDecimal,
                        BigDecimal.ZERO, BillType.IN.getCode(), CoinType.INTE.getCode(),
                        DetailEnums.CLIMBING_TOWER_PA.getCode(), "任务包-"+packageName+"-直推奖励", id);
            }
            AppUserVo userVo = queryById(appUserVo.getParentId());
            //间推给上家15%
            if (userVo != null && userVo.getParentId() != null) {
                String jianTui = "15";
                BigDecimal jtBigDecimal = income.multiply(new BigDecimal(jianTui)).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
                if (jtBigDecimal.compareTo(BigDecimal.ZERO) > 0) {
                    appAssetService.addIntegral(userVo.getParentId(), jtBigDecimal);
                    appDetailService.insert(userVo.getParentId(), jtBigDecimal,
                            BigDecimal.ZERO, BillType.IN.getCode(), CoinType.INTE.getCode(),
                            DetailEnums.CLIMBING_TOWER_PA.getCode(), "任务包-"+packageName+"-间推奖励", id);
                }
            }
        }

    }

    @Override
    public List<AppUser> selToday(LocalDateTime startOfDay, LocalDateTime endOfDay) {
        LambdaQueryWrapper<AppUser> appUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        appUserLambdaQueryWrapper.between(AppUser::getCreateTime, startOfDay, endOfDay);
        return baseMapper.selectList(appUserLambdaQueryWrapper);
    }

    @Override
    public int setParent(SetAppParentBo bo) {
        //根据手机号查询用户
        AppUserVo userVo = queryByPhone(bo.getPhone());
        if (userVo != null){
            LambdaUpdateWrapper<AppUser> appUserLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            appUserLambdaUpdateWrapper.eq(AppUser::getId, bo.getId());
            appUserLambdaUpdateWrapper.set(AppUser::getParentId, userVo.getId());
            baseMapper.update(null, appUserLambdaUpdateWrapper);
        }else {
            throw new ServiceException("手机号不存在");
        }
        return 0;
    }

    @Override
    public HashMap<String, Object> inviteCodeImage(Long id) {
        AppUserVo user = queryById(id);
        if (StringUtils.isBlank(user.getInviteCode())) {
            user.setInviteCode(ShareCodeUtil.getSerialCode(user.getId().intValue()));
            AppUserBo userBo = BeanUtil.toBean(user, AppUserBo.class);
            updateByBo(userBo);
        }
        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("inviteCode", user.getInviteCode());
        String inviteUrl = Constants.INVITE_URL + user.getInviteCode();
        hashMap.put("inviteUrl", inviteUrl);
        String inviteCodeImage = null;
        try {
            String base64 = CreateImageUtils.generateQRCodeBase64(inviteUrl, 250, 250);
            inviteCodeImage = "data:image/png;base64," + base64;
        } catch (Exception k) {
            inviteCodeImage = "";
        }
        hashMap.put("inviteCodeImage", inviteCodeImage);
        hashMap.put("isBind", user.getParentId() != null);
        return hashMap;
    }

    @Override
    public boolean isManRiHuo(Long id) {
        LambdaQueryWrapper<AppUser> appUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        appUserLambdaQueryWrapper.eq(AppUser::getParentId, id);
        List<String> startTimeAndEndTime = DateUtils.getStartTimeAndEndTime();
        appUserLambdaQueryWrapper.ge(AppUser::getCreateTime, startTimeAndEndTime.get(0));
        appUserLambdaQueryWrapper.le(AppUser::getCreateTime, startTimeAndEndTime.get(1));
        List<AppUser> appUsers = baseMapper.selectList(appUserLambdaQueryWrapper);
        if (CollUtil.isEmpty(appUsers)){
            return false;
        }
        if (appUsers.size() < 2){
            return false;
        }
        int count = 0;
        String typeKey = CacheConstants.ADVERTISING;
        for (AppUser appUser : appUsers) {
             String key = typeKey + appUser.getId();
             if (RedisUtils.hasKey(key)){
                 Integer c = RedisUtils.getCacheObject(key);
                 if (c >= 6){
                     count++;
                 }
             }
        }
        if (count >= 2){
            return true;
        }
        return false;
    }

    @Override
    public void setPassWord(Long id, String password) {
        //修改密码
        updatePassword(id, password);
    }

    @Override
    public List<AppUserVo> selUserByPhoneAndId(String keyWord) {
        if (StringUtils.isBlank(keyWord)){
            return new ArrayList<>();
        }
        LambdaQueryWrapper<AppUser> wrapper = new LambdaQueryWrapper<>();

        wrapper.and(w ->
                // 0=公开：昵称、ID、手机号都能搜
                w.nested(w1 -> w1.eq(AppUser::getSearchType, 0)
                                .and(i -> i.like(AppUser::getUserName, keyWord)
                                        .or().eq(AppUser::getId, keyWord)
                                        .or().like(AppUser::getPhone, keyWord))
                        )
                        // 1=仅ID可搜
                        .or(w2 -> w2.eq(AppUser::getSearchType, 1)
                                .and(i -> i.eq(AppUser::getId, keyWord))
                        )
                        // 2=仅手机号可搜
                        .or(w3 -> w3.eq(AppUser::getSearchType, 2)
                                .and(i -> i.like(AppUser::getPhone, keyWord))
                        )
        );

        return baseMapper.selectVoList(wrapper);
    }




    /**
     * 获取指定用户的活度总和
     *
     * @param userIds 用户IDS
     * @return
     */
    private BigDecimal getLivenessSum(List<Long> userIds) {
        HashSet<Long> ids = new HashSet<>(userIds);
        if (ids.isEmpty()) {
            return BigDecimal.ZERO;
        }
        LambdaQueryWrapper<AppAsset> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(AppAsset::getUserId, ids);
        List<AppAssetVo> appAssetVos = appAssetService.queryList(wrapper);
        if (appAssetVos.isEmpty()) {
            return BigDecimal.ZERO;
        }
        return appAssetVos.stream().map(AppAssetVo::getLiveness).reduce(BigDecimal.ZERO, BigDecimal::add);
    }

}
